Add utility to inspect buildd logs
authorStuart Prescott <stuart@debian.org>
Sun, 23 Feb 2025 06:48:49 +0000 (17:48 +1100)
committerStuart Prescott <stuart@debian.org>
Sun, 23 Feb 2025 06:48:49 +0000 (17:48 +1100)
debian/check-build-logs [new file with mode: 0755]

diff --git a/debian/check-build-logs b/debian/check-build-logs
new file mode 100755 (executable)
index 0000000..76f0465
--- /dev/null
@@ -0,0 +1,104 @@
+#!/usr/bin/python3
+
+from collections import defaultdict
+from pathlib import Path
+import re
+import subprocess
+
+from debian.changelog import Changelog
+
+
+debian_archs = [
+    "amd64",
+    "arm64",
+    "armel",
+    "armhf",
+    "i386",
+    "mips64el",
+    "ppc64el",
+    "riscv64",
+    "s390x",
+]
+
+
+def fetch_build_logs(package: str, version: str) -> None:
+    for a in debian_archs:
+        if not Path(f"{package}_{version}_{a}.log").exists():
+            cmd = [
+                "getbuildlog",
+                package,
+                version,
+                a,
+            ]
+            subprocess.check_call(cmd)
+
+
+def find_bpass(filepath: Path) -> list[str]:
+    with open(filepath, "rt") as fh:
+        bpass = [l for l in fh.readlines() if "BPASS" in l]
+    return bpass
+
+
+def process_logs(package: str, version: str) -> dict[str, list[str]]:
+    filename_re = re.compile(rf"{package}_.*_(.*)\.log")
+
+    result: dict[str, list[str]] = {}
+
+    for logfilepath in Path(".").glob(f"{package}_{version}_*.log"):
+        m = filename_re.match(str(logfilepath))
+        assert m
+        arch = m.group(1)
+        bpasses = find_bpass(logfilepath)
+        result[arch] = bpasses
+    return result
+
+
+def print_table(result: dict[str, list[str]]):
+    tests: dict[str, list[str]] = defaultdict(list)
+    checked = sorted(result.keys())
+
+    linere = re.compile(r"Test +#(\d+): BPASS +(.*)")
+    for arch in checked:
+        for line in result[arch]:
+            m = linere.search(line)
+            assert m
+            testname = m.group(2)
+            tests[testname].append(arch)
+
+    collapse_format = False
+    max_len = max(len(t) for t in tests.keys())
+
+    if collapse_format:
+        max_len //= 2
+
+    print(" " * (max_len + 1), end="")
+    for a in debian_archs:
+        print(f"{a} ", end="")
+    print()
+
+    for test, archs in tests.items():
+        if collapse_format:
+            print(test)
+            print(" " * max_len, end="")
+        else:
+            print(f"{test:{max_len+1}}", end="")
+        for a in debian_archs:
+            if a not in checked:
+                icon = "?"
+            elif a in archs:
+                icon = "✔"
+            else:
+                icon = "✘"
+            print(f"{icon: ^{len(a)}} ", end="")
+        print()
+
+
+if __name__ == "__main__":
+    with open("debian/changelog") as fh:
+        ch = Changelog(fh)
+    pkg = ch.package
+    ver = str(ch.version)
+
+    fetch_build_logs(pkg, ver)
+    results = process_logs(pkg, ver)
+    print_table(results)